﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using System.Xml;
using Marmat.FrameWork;
using Marmat.Foundation;

namespace Marmat.Template.WinForm
{
    /// <summary>
    /// 通用的单据管理实现。
    /// </summary>
    /// <typeparam name="Entity"></typeparam>
    /// <typeparam name="DataSource"></typeparam>
    [EditorBrowsable(EditorBrowsableState.Never)]
    public abstract class DocumentManagement<Entity, DataSource> : IDocumentManagement, IMenuItemBuilder
    {

        internal List<IDocumentViewForm<Entity, DataSource>> viewFormCollection = new List<IDocumentViewForm<Entity, DataSource>>();

        /// <summary>
        /// 构建单据管理的实例。
        /// </summary>
        protected DocumentManagement()
        {
        }

        /// <summary>
        ///获取或设置单据的标题。
        /// </summary>
        public string Text { get; set; }

        /// <summary>
        /// 获取或设置是否允许创建。
        /// </summary>
        public virtual bool AllowCreate { get; set; } = true;

        /// <summary>
        ///  获取或设置是否允许编辑。
        /// </summary>
        public virtual bool AllowEdit { get; set; } = true;

        /// <summary>
        /// 获取或设置是否允许删除。
        /// </summary>
        public virtual bool AllowDelete { get; set; } = true;

        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 用户模块的命令接口。
        /// </summary>
        public IDocumentCommandBase<Entity, DataSource> Command { get; set; }

        /// <summary>
        /// 获取或设置视图面板控制器。
        /// 只有需要对ViewForm的接口做扩展时才需要扩展
        /// </summary>
        internal Func<IDocumentViewFormController<Entity, DataSource>> ViewFormController { get; set; }

        /// <summary>
        /// 获取或设置视图面板。
        /// </summary>
        internal Func<IDocumentViewForm<Entity, DataSource>> ViewFormPanel { get; set; }

        /// <summary>
        /// 获取或设置编辑控制器
        /// </summary>
        internal Func<IDocumentEditFormController<Entity, DataSource>> EditFormController { get; set; }

        /// <summary>
        /// 获取或设置编辑面板
        /// </summary>
        internal Func<IDocumentEditForm<Entity, DataSource>> EditFormPanel { get; set; }

        /// <summary>
        /// 获取列集合。
        /// </summary>
        /// <returns></returns>
        protected internal abstract IEnumerable<ColumnEntity> GetColumnCollection();

        /// <summary>
        /// 打开用户视图窗体
        /// </summary>
        public virtual void ShowViewForm()
        {
            IMainForm mainForm = SystemCommand.GetService<IMainForm>();
            Form form = this.GetViewForm();
            mainForm.AddForm(form);
        }

        /// <summary>
        /// 打开用户视图窗体
        /// </summary>
        public virtual void ShowViewForm(IDocumentViewFormController<Entity, DataSource> controller)
        {
            IMainForm mainForm = SystemCommand.GetService<IMainForm>();
            Form form = this.GetViewForm(controller);
            mainForm.AddForm(form);
        }

        /// <summary>
        /// 获取用户视图窗体。
        /// </summary>
        public virtual Form GetViewForm()
        {
            var controller = this.ViewFormController.Invoke();
            return GetViewForm(controller);
        }

        /// <summary>
        /// 获取用户视图窗体。
        /// </summary>
        public virtual Form GetViewForm(IDocumentViewFormController<Entity, DataSource> controller)
        {
            var formPanel = this.ViewFormPanel.Invoke();
            controller.Management = this;
            controller.FormPanel = formPanel;
            if (formPanel is Control panel)
                panel.Text = this.Text ?? this.Name;
            formPanel.Controller = controller;
            Marmat.Foundation.IViewForm viewForm = SystemCommand.GetService<Marmat.Foundation.IViewForm>();
            viewForm.SetRoute(controller);
            if (viewForm is Form form)
            {
                // 为监听做准备。
                viewFormCollection.Add(formPanel);
                if (formPanel is Control control)
                    control.Disposed += (_, _) => viewFormCollection.Remove(formPanel);
                form.Name = this.Name;
                return form;
            }
            else
                throw new InvalidCastException("viewForm 无法转换为System.Windows.Forms.Form");
        }


        /// <summary>
        /// 打开创建的编辑窗体。
        /// </summary>
        public virtual void ShowCreateForm()
        {
            Form form = this.GetCreateForm();
            if (form != null)
            {
                IMainForm mainForm = SystemCommand.GetService<IMainForm>();
                mainForm.AddForm(form);
            }
        }

        /// <summary>
        /// 打开创建的编辑窗体。
        /// </summary>
        public virtual void ShowCreateForm(params object[] arguments)
        {
            Form form = this.GetCreateForm(arguments);
            if (form != null)
            {
                IMainForm mainForm = SystemCommand.GetService<IMainForm>();
                mainForm.AddForm(form);
            }
        }

        /// <summary>
        /// 打开用户编辑窗体。
        /// </summary>
        /// <param name="id">主键值</param>
        public void ShowEditForm(string id)
        {
            this.ShowEditForm(id as object);
        }

        /// <summary>
        /// 打开用户编辑窗体。
        /// </summary>
        /// <param name="id">主键值</param>
        public void ShowEditForm(int id)
        {
            this.ShowEditForm(id as object);
        }

        /// <summary>
        /// 打开用户编辑窗体。
        /// </summary>
        /// <param name="id">主键值</param>
        public virtual void ShowEditForm(object id)
        {
            Form form = this.GetEditForm(id);
            if (form != null)
            {
                IMainForm mainForm = SystemCommand.GetService<IMainForm>();
                mainForm.AddForm(form);
            }
        }


        /// <summary>
        /// 打开用户编辑窗体。
        /// </summary>
        /// <param name="controller">控制器</param>
        protected virtual void ShowEditForm(IDocumentEditFormController<Entity, DataSource> controller)
        {
            Form form = this.GetEditForm(controller);
            if (form != null)
            {
                IMainForm mainForm = SystemCommand.GetService<IMainForm>();
                mainForm.AddForm(form);
            }
        }

        /// <summary>
        /// 构建编辑窗体的控制器实例。
        /// </summary>
        /// <returns></returns>
        protected virtual IDocumentEditFormController<Entity, DataSource> CreateEditFormController()
        {
            IDocumentEditFormController<Entity, DataSource> controller = this.EditFormController.Invoke();
            controller.Management = this;
            controller.AllowEdit = this.AllowEdit;
            controller.AllowDelete = this.AllowDelete;
            controller.FormPanel = this.EditFormPanel.Invoke();
            controller.FormPanel.Controller = controller;
            return controller;
        }


        /// <summary>
        /// 获取单据的创建窗体。
        /// </summary>
        /// <returns></returns>
        public virtual Form GetCreateForm()
        {
            IDocumentEditFormController<Entity, DataSource> controller = this.CreateEditFormController();
            controller.CreateDataObject(null);
            return this.GetEditForm(controller);
        }

        /// <summary>
        /// 获取单据的创建窗体。
        /// </summary>
        /// <param name="arguments">创建时带入的参数，可以在创建时用于默认值或参与逻辑判断。</param>
        /// <returns></returns>
        public virtual Form GetCreateForm(params object[] arguments)
        {
            IDocumentEditFormController<Entity, DataSource> controller = this.CreateEditFormController();
            controller.CreateDataObject(arguments);
            return this.GetEditForm(controller);
        }

        /// <summary>
        /// 获取用户创建窗体。
        /// </summary>
        /// <returns></returns>
        public virtual Form GetEditForm(int id)
        {
            return GetEditForm(id as object);
        }

        /// <summary>
        /// 获取用户创建窗体。
        /// </summary>
        /// <returns></returns>
        public virtual Form GetEditForm(string id)
        {
            return GetEditForm(id as object);
        }

        /// <summary>
        /// 获取用户创建窗体。
        /// </summary>
        /// <returns></returns>
        public virtual Form GetEditForm(object id)
        {
            IDocumentEditFormController<Entity, DataSource> controller = this.CreateEditFormController();
            controller.Id = id;
            controller.LoadDataObject();
            return this.GetEditForm(controller);
        }

        /// <summary>
        /// 获取用户编辑窗体。
        /// </summary>
        /// <param name="controller">控制器</param>
        /// <returns></returns>
        protected virtual Form GetEditForm(IDocumentEditFormController<Entity, DataSource> controller)
        {
            Marmat.Foundation.IEditForm editForm = SystemCommand.GetService<Marmat.Foundation.IEditForm>();
            if (editForm is not Form form)
                throw new InvalidCastException("Marmat.Foundation.IEditForm 无法转换为System.Windows.Forms.Form");

            SheetControl sheetControl = new();
            sheetControl.SetRoute(controller);
            editForm.SetRoute(sheetControl);
            return form;
        }

        void IMenuItemBuilder.Builder(List<IMenu> menus)
        {
            var route = this.GetType().GetCustomAttribute<MenuAttribute>();
            Foundation.Menu menu;
            string parent = null;
            if (route is not null && !string.IsNullOrEmpty(route.Path))
            {
                foreach (var path in route.Path.Split('\\', '/'))
                {
                    if (!string.IsNullOrEmpty(path) && !menus.Exists(x => x.Name == path))
                    {
                        menu = new Foundation.Menu();
                        menu.Name = path;
                        menu.Parent = parent;
                        parent = menu.Name;
                        menus.Add(menu);
                    }
                }
            }
            menu = new Foundation.Menu();
            menu.Name = this.Name;
            menu.Parent = parent;
            menus.Add(menu);
        }

        void IMenuItemBuilder.ItemClick(IMenu menu)
        {
            IMainForm mainForm = SystemCommand.GetService<IMainForm>();
            if (this.Name == menu.Name)
            {
                if (mainForm.ContainsForm(menu.Name))
                    mainForm.SelectedFormName = menu.Name;
                else
                    this.ShowViewForm();
            }
        }
    }

    /// <summary>
    /// 基于实体对象的单据模块管理器
    /// </summary>
    /// <typeparam name="Entity"></typeparam>
    public class DocumentManagement<Entity> : DocumentManagement<Entity, Entity[]> where Entity : class, new()
    {

        /// <summary>
        /// 构建基于实体对象的单据模块管理器
        /// </summary>
        public DocumentManagement()
        {
            this.Command = SystemCommand.GetService<IDefaultDocumentCommand<Entity>>();
        }

        /// <summary>
        /// 构建基于实体对象的单据模块管理器
        /// </summary>
        /// <param name="command"></param>
        public DocumentManagement(IDocumentCommand<Entity> command)
        {
            this.Command = command;
        }

        /// <summary>
        /// 构建基于实体对象的单据模块管理器
        /// </summary>
        /// <param name="command"></param>
        public DocumentManagement(IDocumentCommandPagination<Entity> command)
        {
            this.Command = command;
        }

        /// <summary>
        /// 设置视图控制器属性组。
        /// </summary>
        /// <typeparam name="Controller">视图控制器</typeparam>
        /// <typeparam name="Panel">视图面板</typeparam>
        public void SetViewFormProperties<Controller, Panel>() where Controller : IDocumentViewFormController<Entity>, new() where Panel : IDocumentViewForm<Entity>, new()
        {
            this.SetViewFormController<Controller>();
            this.SetViewFormPanel<Panel>();
        }

        /// <summary>
        /// 设置编辑控制器属性组。
        /// </summary>
        /// <typeparam name="Controller">视图控制器</typeparam>
        /// <typeparam name="Panel">视图面板</typeparam>
        public void SetEditFormProperties<Controller, Panel>() where Controller : IDocumentEditFormController<Entity>, new() where Panel : IDocumentEditForm<Entity>, new()
        {
            this.SetEditFormController<Controller>();
            this.SetEditFormPanel<Panel>();
        }

        /// <summary>
        /// 设置视图控制器。
        /// </summary>
        /// <typeparam name="Controller">视图控制器</typeparam>
        public void SetViewFormController<Controller>() where Controller : IDocumentViewFormController<Entity>, new()
        {
            this.ViewFormController = () => new Controller();
        }

        /// <summary>
        /// 设置视图面板。
        /// </summary>
        /// <typeparam name="Panel">视图面板</typeparam>
        public void SetViewFormPanel<Panel>() where Panel : IDocumentViewForm<Entity>, new()
        {
            this.ViewFormPanel = () => new Panel();
        }


        /// <summary>
        /// 设置编辑控制器。
        /// </summary>
        /// <typeparam name="Controller">编辑控制器</typeparam>
        public void SetEditFormController<Controller>() where Controller : IDocumentEditFormController<Entity>, new()
        {
            this.EditFormController = () => new Controller();
        }

        /// <summary>
        /// 设置编辑编辑面板。
        /// </summary>
        /// <typeparam name="Panel">编辑面板</typeparam>
        public void SetEditFormPanel<Panel>() where Panel : IDocumentEditForm<Entity>, new()
        {
            this.EditFormPanel = () => new Panel();
        }

        /// <summary>
        /// 用户模块的命令接口。
        /// </summary>
        public new IDocumentCommandBase<Entity> Command { get => (IDocumentCommandBase<Entity>)base.Command; set => base.Command = value; }

        /// <summary>
        /// 获取或设置视图面板控制器
        /// 只有需要对ViewForm的接口做扩展时才需要扩展
        /// </summary>
        internal new Func<IDocumentViewFormController<Entity>> ViewFormController { get => (Func<IDocumentViewFormController<Entity>>)base.ViewFormController; set => base.ViewFormController = value; }

        /// <summary>
        /// 获取或设置视图面板。
        /// </summary>
        internal new Func<IDocumentViewForm<Entity>> ViewFormPanel { get => (Func<IDocumentViewForm<Entity>>)base.ViewFormPanel; set => base.ViewFormPanel = value; }

        /// <summary>
        /// 获取编辑面板控制器
        /// </summary>
        internal new Func<IDocumentEditFormController<Entity>> EditFormController { get => (Func<IDocumentEditFormController<Entity>>)base.EditFormController; set => base.EditFormController = value; }

        /// <summary>
        /// 获取编辑面板
        /// </summary>
        internal new Func<IDocumentEditForm<Entity>> EditFormPanel { get => base.EditFormPanel as Func<IDocumentEditForm<Entity>>; set => base.EditFormPanel = value; }

        /// <summary>
        /// 获取用户视图窗体。
        /// </summary>
        /// <returns></returns>
        public override Form GetViewForm()
        {
            if (this.ViewFormPanel is null)
                this.ViewFormPanel = () => new DocumentViewForm<Entity>();
            if (this.ViewFormController is null)
                this.ViewFormController = () => new DocumentViewFormController<Entity>();
            return base.GetViewForm();
        }

        /// <summary>
        /// 构建编辑窗体的控制器实例。
        /// </summary>
        /// <returns></returns>
        protected override IDocumentEditFormController<Entity, Entity[]> CreateEditFormController()
        {
            if (this.EditFormPanel is null)
                this.EditFormPanel = () => new DocumentEditForm<Entity>();
            if (this.EditFormController is null)
                this.EditFormController = () => new DocumentEditFormController<Entity>();
            return base.CreateEditFormController();
        }

        /// <summary>
        /// 获取列集合。
        /// </summary>
        /// <returns></returns>
        protected internal override IEnumerable<ColumnEntity> GetColumnCollection()
        {
            MemberInfo[] members = typeof(Entity).GetMembers();
            List<ColumnEntity> columns = new List<ColumnEntity>();

            foreach (MemberInfo member in members)
            {
                ColumnEntity column = new ColumnEntity();
                if (member is FieldInfo field)
                {
                    column.Name = field.Name;
                    column.DataType = field.FieldType;
                    column.Caption = field.Name;
                }
                else if (member is PropertyInfo property)
                {
                    column.Name = property.Name;
                    column.DataType = property.PropertyType;
                    column.Caption = property.Name;
                }
                else
                    continue;
                columns.Add(column);

                #region "补充对字段的说明"
                System.ComponentModel.DescriptionAttribute description = member.GetCustomAttribute<System.ComponentModel.DescriptionAttribute>();
                if (description != null)
                    column.Caption = description.Description;
                else if (member.GetXmlDescription(out string summary))
                    column.Caption = summary;
                #endregion
            }
            return columns;
        }
    }

    /// <summary>
    /// 基于DataTable的单据模块管理器
    /// </summary>
    public class DocumentManagement : DocumentManagement<System.Data.DataRow, System.Data.DataTable>
    {

        /// <summary>
        /// 构建基于DataTable的单据模块管理器
        /// </summary>
        public DocumentManagement()
        {
            this.Command = SystemCommand.GetService<IDefaultDocumentCommand>();
        }

        /// <summary>
        /// 构建基于DataTable的单据模块管理器
        /// </summary>
        /// <param name="command">命令实例</param>
        public DocumentManagement(IDocumentCommand command)
        {
            this.Command = command;
        }

        /// <summary>
        /// 构建基于DataTable的单据模块管理器
        /// </summary>
        /// <param name="command">命令实例</param>
        public DocumentManagement(IDocumentCommand<System.Data.DataRow, System.Data.DataTable> command)
        {
            base.Command = command;
        }

        /// <summary>
        /// 构建基于DataTable的单据模块管理器
        /// </summary>
        /// <param name="command">命令实例</param>
        public DocumentManagement(IDocumentCommandPagination<System.Data.DataRow, System.Data.DataTable> command)
        {
            base.Command = command;
        }

        /// <summary>
        /// 设置视图控制器。
        /// </summary>
        /// <typeparam name="Controller">视图控制器</typeparam>
        public void SetViewFormController<Controller>() where Controller : IViewFormController, new()
        {
            this.ViewFormController = () => new Controller();
        }

        /// <summary>
        /// 设置视图面板。
        /// </summary>
        /// <typeparam name="Panel">视图面板</typeparam>
        public void SetViewFormPanel<Panel>() where Panel : IDocumentViewForm, new()
        {
            this.ViewFormPanel = () => new Panel();
        }

        /// <summary>
        /// 设置编辑控制器。
        /// </summary>
        /// <typeparam name="Controller">编辑控制器</typeparam>
        public void SetEditFormController<Controller>() where Controller : IDocumentEditFormController, new()
        {
            this.EditFormController = () => new Controller();
        }

        /// <summary>
        /// 设置编辑编辑面板。
        /// </summary>
        /// <typeparam name="Panel">编辑面板</typeparam>
        public void SetEditFormPanel<Panel>() where Panel : IDocumentEditForm, new()
        {
            this.EditFormPanel = () => new Panel();
        }

        /// <summary>
        /// 用户模块的命令接口。
        /// </summary>
        public new IDocumentCommandBase Command { get => (IDocumentCommandBase)base.Command; set => base.Command = value; }

        /// <summary>
        /// 获取或设置视图面板控制器。
        /// </summary>
        public new Func<IViewFormController> ViewFormController { get => (Func<IViewFormController>)base.ViewFormController; set => base.ViewFormController = value; }

        /// <summary>
        /// 获取或设置视图面板。
        /// </summary>
        public new Func<IDocumentViewForm> ViewFormPanel { get => (Func<IDocumentViewForm>)base.ViewFormPanel; set => base.ViewFormPanel = value; }

        /// <summary>
        /// 获取编辑面板控制器
        /// </summary>
        public new Func<IDocumentEditFormController> EditFormController { get => (Func<IDocumentEditFormController>)base.EditFormController; set => base.EditFormController = value; }

        /// <summary>
        /// 获取编辑面板
        /// </summary>
        public new Func<IDocumentEditForm> EditFormPanel { get => base.EditFormPanel as Func<IDocumentEditForm>; set => base.EditFormPanel = value; }

        /// <summary>
        /// 获取列集合。
        /// </summary>
        /// <returns></returns>
        internal protected override IEnumerable<ColumnEntity> GetColumnCollection()
        {
            System.Data.DataTable data = this.GetFillSchema();
            List<ColumnEntity> columns = new List<ColumnEntity>();
            foreach (System.Data.DataColumn dataColumn in data.Columns)
            {
                ColumnEntity column = new ColumnEntity();
                column.Name = dataColumn.ColumnName;
                column.DataType = dataColumn.DataType;
                column.Caption = dataColumn.Caption;
                columns.Add(column);
            }
            return columns;
        }

        /// <summary>
        ///  加载指定 System.Data.DataTable 的架构。
        /// </summary>
        /// <returns></returns>
        internal System.Data.DataTable GetFillSchema()
        {
            if (_fillSchema is null)
                _fillSchema = this.Command.FillSchema();
            return _fillSchema;
        }
        private System.Data.DataTable _fillSchema;

        /// <summary>
        /// 获取用户视图窗体。
        /// </summary>
        /// <returns></returns>
        public override Form GetViewForm()
        {
            if (this.ViewFormPanel is null)
                this.ViewFormPanel = () => new DocumentViewForm();
            if (this.ViewFormController is null)
                this.ViewFormController = () => new DocumentViewFormController();
            return base.GetViewForm();
        }

        /// <summary>
        /// 构建编辑窗体的控制器实例。
        /// </summary>
        /// <returns></returns>
        protected override IDocumentEditFormController<DataRow, DataTable> CreateEditFormController()
        {
            if (this.EditFormPanel is null)
                this.EditFormPanel = () => new DocumentEditForm();
            if (this.EditFormController is null)
                this.EditFormController = () => new DocumentEditFormController();
            return base.CreateEditFormController();
        }
    }
}
